import { _decorator, Component, Node, director } from 'cc'
const { ccclass, property } = _decorator

import { levels, ILevel } from '../../Levels'

// 引入地图组件
import { TileMapManager, TILE_WIDTH, TILE_HEIGHT } from '../Tile/TileMapManager'
import { createUINode } from '../../Utils'
import { EVENT_NAME, DIRECTION, PLAYER_STATE_TYPE_ENUM, ENTITY_TYPE_ENUM } from '../../Enums'

// 引入单例
import DataManager from '../../Runtime/DataManager'
import EventManager from '../../Runtime/EventManager'
import FaderManager from '../../Runtime/FaderManager'

// 引入player
import { PlayerManager } from '../Player/PlayerManager'

// 引入木头人
import { WoodenskeletonManager } from '../Woodenskeleton/WoodenskeletonManager'
import {IronskeletonManager} from '../Ironskeleton/IronskeletonManager'

// 引入尖刺
import { SpkiesManager } from '../Spkies/SpkiesManager'

// 引入地裂
import { BurstsManager } from '../Bursts/BurstsManager'

// 引入门
import { DoorManager } from '../Door/DoorManager'

// 引入烟雾
import { SmokeManager } from '../Smoke/SmokeManager'

// 引入震动
import { ShakeManager } from '../UI/ShakeManager'

// 总管理
@ccclass('BattleManager')
export class BattleManager extends Component {
  // currentLevel = 1 //第几关
  level: ILevel | null = null // 当前关卡数据
  stage: Node | null = null // 舞台
  tileMap: Node | null = null // 地图

  smokeLayer: Node | null = null // 烟雾层

  hasInit = false // 是否初始化

  // 绑定到事件中心
  onLoad() {
    // DataManager.Instance.levelIndex = 2
    EventManager.Instance.on(EVENT_NAME.TO_NEXT_LEVEL, this.toNextLevel, this)
    EventManager.Instance.on('PLAYER_MOVE_END', this.onPlayerMoveEnd, this)
    EventManager.Instance.on('SHOW_SMOKE', this.onShowSmoke, this)
    EventManager.Instance.on('RECORD', this.record, this)
    EventManager.Instance.on('RESTORE', this.restore, this)
    EventManager.Instance.on('RESTART', this.initLevel, this)
    EventManager.Instance.on('OUT', this.out, this)
  }

  // 卸载时进行解绑
  onDestroy() {
    EventManager.Instance.off(EVENT_NAME.TO_NEXT_LEVEL, this.toNextLevel)
    EventManager.Instance.off('PLAYER_MOVE_END', this.onPlayerMoveEnd)
    EventManager.Instance.off('SHOW_SMOKE', this.onShowSmoke)
    EventManager.Instance.off('RECORD', this.record)
    EventManager.Instance.off('RESTORE', this.restore)
    EventManager.Instance.off('RESTART', this.initLevel)
    EventManager.Instance.off('OUT', this.out)
  }

  start() {
    this.generateStage() // 创建舞台
    this.initLevel() // 初始化关卡
  }

  // 退出
  out() {
    FaderManager.Instance.fadeIn()
    // 跳转场景
    director.loadScene('Start')
  }

  // 创建一个舞台
  generateStage() {
    const stage = createUINode()
    this.node.addChild(stage)

    this.stage = stage
    this.stage.addComponent(ShakeManager)
  }

  // 初始化关卡
  async initLevel() {
    const level = levels[`level${DataManager.Instance.levelIndex}`]

    if (level) {
      if(this.hasInit) {
        // 淡入
        await FaderManager.Instance.fadeIn()
      } else {
        await FaderManager.Instance.mask()
      }

      this.clear() // 清空
      this.level = level //存一份

      // 存到数据中心
      const { mapInfo } = level
      DataManager.Instance.mapInfo = mapInfo
      DataManager.Instance.mapRowCount = mapInfo.length || 0
      DataManager.Instance.mapColCount = mapInfo[0].length || 0

      const promiseAll = [ // 创建地图
        this.generateTileMap(),
        // 创建木头人
        this.generateWoodenskeleton(),

        // 创建门
        this.generateDoor(),

        // 创建地裂
        this.generateBursts(),

        // 创建尖刺
        this.generateSpkies(),

        // 创建烟雾node
        this.generateSmokeLayer(),

        // 创建player
        this.generatePlayer(),
      ]
      await Promise.all(promiseAll)

      // 淡出
      await FaderManager.Instance.fadeOut()

      this.hasInit = true
    } else {
      this.out()
    }
  }

  // 到下一个关卡
  toNextLevel() {
    DataManager.Instance.levelIndex++
    console.log('[ 下一关 ] >', DataManager.Instance.levelIndex)
    this.initLevel()
  }

  // 加载关卡时清空
  clear() {
    this.stage?.destroyAllChildren()
    DataManager.Instance.reset()
  }

  // 创建地图
  async generateTileMap() {
    // 创建一个地图
    const tileMap = createUINode()
    this.stage.addChild(tileMap)
    this.tileMap = tileMap

    // 初始化地图
    const tileMapManager = tileMap.addComponent(TileMapManager)
   await tileMapManager.init()

    // 让地图居中显示
    this.adjustTileMapPosition()
  }

  // 调整地图位置
  adjustTileMapPosition() {
    const { mapColCount, mapRowCount } = DataManager.Instance
    const disX = (TILE_WIDTH * mapColCount) / 2
    const disY = (TILE_HEIGHT * mapRowCount) / 2 + 80

    this.stage.getComponent(ShakeManager).stop()
    this.stage.setPosition(-disX, disY)
  }

  // 创建player
  async generatePlayer() {
    const player = createUINode()
    this.stage.addChild(player)

    // 添加player组件
    const playerManager = player.addComponent(PlayerManager)
    await playerManager.init(this.level?.player)

    DataManager.Instance.player = playerManager
    // 玩家出生的时候也需要调整敌人的方向
    EventManager.Instance.emit('PLAYER_BIRTH', true)
  }

  // 创建木头人
  async generateWoodenskeleton() {
    const { enemies } = this.level
    let promises = []
    enemies.forEach(enemy => {
      const node = createUINode()
      this.stage.addChild(node)
      let type = enemy.type
      const Manager = type === ENTITY_TYPE_ENUM.WOODENSKELETON ? WoodenskeletonManager : IronskeletonManager

      const manager = node.addComponent(Manager)
      promises.push(manager.init(enemy))
      DataManager.Instance.woodenskeletons.push(manager)
    })

    await Promise.all(promises)

    // const woodenskeleton = createUINode()
    // this.stage.addChild(woodenskeleton)

    // const woodenskeletonManager = woodenskeleton.addComponent(WoodenskeletonManager)
    // await woodenskeletonManager.init({
    //   x: 2,
    //   y: 2,
    //   direction: DIRECTION.TOP,
    //   state: PLAYER_STATE_TYPE_ENUM.IDLE,
    //   type: ENTITY_TYPE_ENUM.WOODENSKELETON,
    // })

    // DataManager.Instance.woodenskeletons.push(woodenskeletonManager)


    // // 创建无法攻击玩家的敌人
    // await this.generateWoodenskeleton1()
  }

  // // 创建无法攻击玩家的敌人
  // async generateWoodenskeleton1() {
  //   const woodenskeleton = createUINode()
  //   this.stage.addChild(woodenskeleton)

  //   const woodenskeletonManager = woodenskeleton.addComponent(IronskeletonManager)
  //   await woodenskeletonManager.init({
  //     x: 2,
  //     y: 5,
  //     direction: DIRECTION.TOP,
  //     state: PLAYER_STATE_TYPE_ENUM.IDLE,
  //     type: ENTITY_TYPE_ENUM.IRONSKELETON,
  //   })

  //   DataManager.Instance.woodenskeletons.push(woodenskeletonManager)
  // }

  // 创建地裂
  async generateBursts() {
    const { bursts } = this.level
    let promises = []
    bursts.forEach(item => {
      const node = createUINode()
      this.stage.addChild(node)

      const burstsManager = node.addComponent(BurstsManager)
      promises.push(burstsManager.init(item))
      DataManager.Instance.bursts.push(burstsManager)
    })

    await Promise.all(promises)

    // const bursts = createUINode()
    // this.stage.addChild(bursts)

    // const burstsManager = bursts.addComponent(BurstsManager)
    // await burstsManager.init({
    //   x: 2,
    //   y: 7,
    //   direction: DIRECTION.TOP,
    //   state: PLAYER_STATE_TYPE_ENUM.IDLE,
    //   type: ENTITY_TYPE_ENUM.BURSTS,
    // })

    // DataManager.Instance.bursts.push(burstsManager)
  }

  // 创建门
  async generateDoor() {
    const door = createUINode()
    this.stage.addChild(door)

    const doorManager = door.addComponent(DoorManager)
    await doorManager.init(this.level?.door)

    // await doorManager.init({
    //   x: 7,
    //   y: 8,
    //   direction: DIRECTION.TOP,
    //   state: PLAYER_STATE_TYPE_ENUM.IDLE,
    //   type: ENTITY_TYPE_ENUM.DOOR,
    // })

    DataManager.Instance.door = doorManager
  }


  // 创建尖刺
  async generateSpkies() {
    const { spikes } = this.level
    let promises = []
    spikes.forEach(item => {
      const node = createUINode()
      this.stage.addChild(node)

      const spkiesManager = node.addComponent(SpkiesManager)
      promises.push(spkiesManager.init(node))
      DataManager.Instance.spkies.push(spkiesManager)
    })

    await Promise.all(promises)

    // const spkies = createUINode()
    // this.stage.addChild(spkies)

    // const spkiesManager = spkies.addComponent(SpkiesManager)
    // await spkiesManager.init({
    //   x: 2,
    //   y: 7,
    //   count: 0,
    //   type: ENTITY_TYPE_ENUM.SPIKES_TWO,
    // })

    // DataManager.Instance.spkies.push(spkiesManager)
  }

  // 创建烟雾node
  async generateSmokeLayer() {
    //  const node = createUINode()
    //  this.stage.addChild(node)
    //  this.smokeLayer = node

    this.smokeLayer = createUINode()
    this.smokeLayer.setParent(this.stage)
  }

  async onShowSmoke(x: number, y: number, direction: DIRECTION) {
    let smokes = DataManager.Instance.smokes
    let item = smokes.find((smoke: SmokeManager) => smoke.state === PLAYER_STATE_TYPE_ENUM.DEATH)
    if(item) {
      item.x = x
      item.y = y
      item.direction = direction
      item.state = PLAYER_STATE_TYPE_ENUM.IDLE
      item.node.setPosition(x * TILE_WIDTH - TILE_WIDTH * 1.5, -y * TILE_HEIGHT + TILE_HEIGHT * 1.5)
    } else {
      const smoke = createUINode()
      smoke.setParent(this.smokeLayer)
      const smokeManager = smoke.addComponent(SmokeManager)
      await smokeManager.init({
        x,
        y,
        direction,
        type: ENTITY_TYPE_ENUM.SMOKE,
        state: PLAYER_STATE_TYPE_ENUM.IDLE,
      })
      DataManager.Instance.smokes.push(smokeManager)
    }
  }

  onPlayerMoveEnd() {
    // console.log('[ 玩家移动结束 ] >')
    let {player, door} = DataManager.Instance
    let {x:playerX, y:playerY} = player
    let {x:doorX, y:doorY, state:doorState} = door

    if (playerX === doorX && playerY === doorY && doorState === PLAYER_STATE_TYPE_ENUM.DEATH) {
      this.toNextLevel()
    }
  }

  // 记录
  record() {
    // let {player, door} = DataManager.Instance

    // // 需要额外进行判断
    // let playerState = player.state
    // if([PLAYER_STATE_TYPE_ENUM.DEATH, PLAYER_STATE_TYPE_ENUM.AIR_DEATH, PLAYER_STATE_TYPE_ENUM.IDLE].indexOf(playerState) !== -1) {
    //   playerState = player.state
    // } else {
    //   playerState = PLAYER_STATE_TYPE_ENUM.IDLE
    // }

    // let item = {
    //   player: {
    //     x: player.x,
    //     y: player.y,
    //     direction: player.direction,
    //     state: playerState,
    //     type: player.type,
    //   },
    //   door: {
    //     x: door.x,
    //     y: door.y,
    //     state: door.state,
    //     type: door.type,
    //   },
    //   // 木头人
    //   woodenskeletons: DataManager.Instance.woodenskeletons.map(item => ({
    //     x: item.x,
    //     y: item.y,
    //     direction: item.direction,
    //     state: item.state,
    //     type: item.type,
    //   })),
    //   // 地裂
    //   bursts: DataManager.Instance.bursts.map(item => ({
    //     x: item.x,
    //     y: item.y,
    //     direction: item.direction,
    //     state: item.state,
    //     type: item.type,
    //   })),
    //   // 尖刺
    //   spkies: DataManager.Instance.spkies.map(item => ({
    //     x: item.x,
    //     y: item.y,
    //     count: item.count,
    //     type: item.type,
    //   })),
    // }

    // // 记录数据
    // DataManager.Instance.records.push(item)

    const item = {
      player: {
        x: DataManager.Instance.player.targetX,
        y: DataManager.Instance.player.targetY,
        state:
          DataManager.Instance.player.state === PLAYER_STATE_TYPE_ENUM.IDLE ||
          DataManager.Instance.player.state === PLAYER_STATE_TYPE_ENUM.DEATH ||
          DataManager.Instance.player.state === PLAYER_STATE_TYPE_ENUM.AIR_DEATH
            ? DataManager.Instance.player.state
            : PLAYER_STATE_TYPE_ENUM.IDLE,
        direction: DataManager.Instance.player.direction,
        type: DataManager.Instance.player.type,
      },
      door: {
        x: DataManager.Instance.door.x,
        y: DataManager.Instance.door.y,
        state: DataManager.Instance.door.state,
        direction: DataManager.Instance.door.direction,
        type: DataManager.Instance.door.type,
      },
      woodenskeletons: DataManager.Instance.woodenskeletons.map(({ x, y, state, direction, type }) => {
        return {
          x,
          y,
          state,
          direction,
          type,
        }
      }),
      spkies: DataManager.Instance.spkies.map(({ x, y, count, type }) => {
        return {
          x,
          y,
          count,
          type,
        }
      }),
      bursts: DataManager.Instance.bursts.map(({ x, y, state, direction, type }) => {
        return {
          x,
          y,
          state,
          direction,
          type,
        }
      }),
    }

    DataManager.Instance.records.push(item)
  }

  // 还原
  restore() {
  //   let {records} = DataManager.Instance
  //   let oldItem = records.pop()
  //  if(oldItem) {
  //   DataManager.Instance.player.x = oldItem.player.x
  //   DataManager.Instance.player.y = oldItem.player.y
  //   DataManager.Instance.player.direction = oldItem.player.direction
  //   DataManager.Instance.player.state = oldItem.player.state
  //   DataManager.Instance.player.type = oldItem.player.type

  //   DataManager.Instance.door.x = oldItem.door.x
  //   DataManager.Instance.door.y = oldItem.door.y
  //   DataManager.Instance.door.state = oldItem.door.state
  //   DataManager.Instance.door.type = oldItem.door.type

  //   DataManager.Instance.woodenskeletons.forEach((item, index) => {
  //     item.x = oldItem.woodenskeletons[index].x
  //     item.y = oldItem.woodenskeletons[index].y
  //     item.direction = oldItem.woodenskeletons[index].direction
  //     item.state = oldItem.woodenskeletons[index].state
  //     item.type = oldItem.woodenskeletons[index].type
  //   })

  //   DataManager.Instance.bursts.forEach((item, index) => {
  //     item.x = oldItem.bursts[index].x
  //     item.y = oldItem.bursts[index].y
  //     item.direction = oldItem.bursts[index].direction
  //     item.state = oldItem.bursts[index].state
  //     item.type = oldItem.bursts[index].type
  //   })

  //   DataManager.Instance.spkies.forEach((item, index) => {
  //     item.x = oldItem.spkies[index].x
  //     item.y = oldItem.spkies[index].y
  //     item.count = oldItem.spkies[index].count
  //     item.type = oldItem.spkies[index].type
  //   })
  //  }
  const data = DataManager.Instance.records.pop()
  if (data) {
    DataManager.Instance.player.x = DataManager.Instance.player.targetX = data.player.x
    DataManager.Instance.player.y = DataManager.Instance.player.targetY = data.player.y
    DataManager.Instance.player.state = data.player.state
    DataManager.Instance.player.direction = data.player.direction

    for (let i = 0; i < data.woodenskeletons.length; i++) {
      const item = data.woodenskeletons[i]
      DataManager.Instance.woodenskeletons[i].x = item.x
      DataManager.Instance.woodenskeletons[i].y = item.y
      DataManager.Instance.woodenskeletons[i].state = item.state
      DataManager.Instance.woodenskeletons[i].direction = item.direction
    }

    for (let i = 0; i < data.spkies.length; i++) {
      const item = data.spkies[i]
      DataManager.Instance.spkies[i].x = item.x
      DataManager.Instance.spkies[i].y = item.y
      DataManager.Instance.spkies[i].count = item.count
    }

    for (let i = 0; i < data.bursts.length; i++) {
      const item = data.bursts[i]
      DataManager.Instance.bursts[i].x = item.x
      DataManager.Instance.bursts[i].y = item.y
      DataManager.Instance.bursts[i].state = item.state
    }

    DataManager.Instance.door.x = data.door.x
    DataManager.Instance.door.y = data.door.y
    DataManager.Instance.door.state = data.door.state
    DataManager.Instance.door.direction = data.door.direction
  } else {
    //TODO 播放游戏音频嘟嘟嘟
  }
  }
}
